package com.byd.dms.fastjson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.util.ParameterizedTypeImpl;
import com.byd.dms.entity.User;
import com.byd.dms.json.Item;
import com.byd.dms.json.Result;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * https://www.cnblogs.com/liqipeng/p/9148545.html
 * http://jverson.com/thinking-in-java/tools/fastjson-deserilize.html
 * https://juejin.cn/post/6844903908184162312
 */
public class ResultDemo {
    private String json = "{\n" +
            "\t\"data\":{\n" +
            "\t\t\"name\":\"username\",\n" +
            "\t\t\"value\":\"root\"\n" +
            "\t},\n" +
            "\t\"msg\":\"Success\",\n" +
            "\t\"ret\":0\n" +
            "}\n";
    
    
    private static <T> Result<T> parseResultV1(String json) {
        return JSONObject.parseObject(json, new TypeReference<Result<T>>() {
        });
    }
    
    private static <T> Result<T> parseResultV2(String json, Class<T> clazz) {
        return JSONObject.parseObject(json, new TypeReference<Result<T>>(clazz) {
        });
    }
    
    private static <T> Result<List<T>> parseListResult1(String json, Class<T> clazz) {
        ParameterizedTypeImpl inner = new ParameterizedTypeImpl(new Type[]{clazz}, null, List.class);
        ParameterizedTypeImpl outer = new ParameterizedTypeImpl(new Type[]{inner}, null, Result.class);
        return JSONObject.parseObject(json, outer);
    }
    
    /**
     * 最终版了 https://www.cnblogs.com/liqipeng/p/9148545.html
     *
     * @param json
     * @param clazz
     * @param <T>
     * @return
     */
    private static <T> Result<List<T>> parseListResult(String json, Class<T> clazz) {
        return JSONObject.parseObject(json, buildType(Result.class, List.class, Item.class));
    }
    
    private static Type buildType(Type... types) {
        ParameterizedTypeImpl beforeType = null;
        if (types != null && types.length > 0) {
            for (int i = types.length - 1; i > 0; i--) {
                beforeType = new ParameterizedTypeImpl(new Type[]{beforeType == null ? types[i] : beforeType}, null, types[i - 1]);
            }
        }
        return beforeType;
    }
    
    @Test
    public void v1() {
        
        
        System.out.println(json);
        
        //编译器就报错了Cannot select parameterized type。
        //JSONObject.parseObject(json, Result<Item>.class);
        
        
    }
    
    @Test
    public void v2() {
        Result result = JSONObject.parseObject(json, Result.class);
        System.out.println("result = " + result);
        Object data = result.getData();
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());  // com.alibaba.fastjson.JSONObject
        
    }
    
    @Test
    public void v3() {
        //Result<Item> result = JSONObject.parseObject(json, new TypeReference<Result<Item>>() {
        //});
        //
        //System.out.println("result = " + result);
        //Object data = result.getData();
        //System.out.println("data = " + data);
        //System.out.println(data.getClass().getName());
        //
        
    }
    
    @Test
    public void v4() {
        Result<Item> result = parseResultV1(json);
        
        System.out.println("result = " + result);
        Object data = result.getData();
        System.out.println("data = " + data);
        
        System.out.println(data.getClass().getName());
        
        System.out.println("===============================");
        String json = "{\"data\":\"Hello,world!\",\"msg\":\"Success\",\"ret\":0}";
        String json2 = "{\"data\":3333,\"msg\":\"Success\",\"ret\":0}";
        result = parseResultV1(json2);
        System.out.println("result = " + result);
        data = result.getData();
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());
        
    }
    
    
    @Test
    public void v5() {
        Result<Item> result = parseResultV2(json, Item.class);
        
        System.out.println("result = " + result);
        Item data = result.getData();
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());
        
        v5_2();
    }
    
    public void v5_2() {
        System.out.println("===============================");
        
        String json = "{\"data\":\"Hello,world!\",\"msg\":\"Success\",\"ret\":0}";
        String json2 = "{\"data\":3333,\"msg\":\"Success\",\"ret\":0}";
        Result<Long> result = parseResultV2(json2, Long.class);
        
        System.out.println("result = " + result);
        Long data = result.getData();
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());
    }
    
    @Test
    public void v6() {
        List<String> strs = new ArrayList<>();
        strs.add("hello");
        strs.add("你好");
        strs.add(" 世界!!!");
        
        Result<List<String>> resultObj = new Result<>(0, "成功", strs);
        String s = JSON.toJSONString(resultObj);
        System.out.println(s); // {"data":["hello","你好"," 世界!!!"],"msg":"成功","ret":0}
        
        Result<List<String>> result = parseListResult1(s, String.class);
        
        
        System.out.println("result = " + result);
        List<String> data = result.getData();
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());
        v6_2();
        
    }
    
    private List<User> getUsers() {
        User user1 = new User("秦疆1号", 3, "男");
        User user2 = new User("秦疆2号", 3, "男");
        User user3 = new User("秦疆3号", 3, "男");
        List<User> users = new ArrayList<User>();
        users.add(user1);
        users.add(user2);
        users.add(user3);
        return users;
    }
    
    public void v6_2() {
        System.out.println("=============== v6_2 ================");
        
        List<User> users = getUsers();
        
        Result<List<User>> resultObj = new Result<>(0, "成功", users);
        String s = JSON.toJSONString(resultObj);
        System.out.println(s);
        
        Result<List<User>> result = parseListResult1(s, User.class);
        
        
        System.out.println("result = " + result);
        List<User> data = result.getData();
        System.out.println(data.get(0).toString());
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());
    }
    
    
    @Test
    public void v7() {
        List<User> users = getUsers();
        Result<List<User>> resultObj = new Result<>(3333, "getUsers成功 ", users);
        String s = JSON.toJSONString(resultObj);
        System.out.println(s);
        Result<List<User>> result = parseListResult1(s, User.class);
        
        System.out.println("result = " + result);
        List<User> data = result.getData();
        System.out.println(data.get(1).toString());
        System.out.println("data = " + data);
        System.out.println(data.getClass().getName());
    }
    
    @Test
    public void v8() {
        /*Type type = new TypeReference<ResultVo<PageVo<DataVo>>>(){}.getType();
        ResultVo<PageVo<DataVo>> resultVo = JSONObject.parseObject(resultJson, type);
    
        // 如果使用 gson 的话则将 TypeReference 换成 TypeToken 即可
        Map map2 = new Gson().fromJson(json, new TypeToken<Map<String, Integer>>(){}.getType());*/
    }
    
    
    @Test
    public void v9() {
        JSONObject.parseObject(json, Result.class);
    }
    
    @Test
    public void v10() {
        JSONObject.parseObject(json, Result.class);
    }
}
